//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package data_anno_task_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/comment_dao"
	"atomgit.com/openlinksaas/api-server/dao/data_anno_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas/api-server/dao/user_dao"
	"atomgit.com/openlinksaas/api-server/dao/watch_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/data_anno_task_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_comment_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_entry_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_watch_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *DataAnnoTaskApiImpl) AddMember(ctx context.Context, req *data_anno_task_api.AddMemberRequest) (*data_anno_task_api.AddMemberResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查信息是否存在
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.AnnoProjectId, req.ProjectId)
	if err != nil {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	if entryItem.EntryType != uint32(project_entry_api.ENTRY_TYPE_ENTRY_TYPE_DATA_ANNO) {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}

	hasUpdatePerm := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)

	if !hasUpdatePerm {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查标注项目是否存在
	annoProjectItem, err := data_anno_dao.AnnoProjectDao.Get(ctx, req.ProjectId, req.AnnoProjectId)
	if err != nil {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	//检查是否已经存在
	exist, err := data_anno_dao.AnnoMemberDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if exist {
		return &data_anno_task_api.AddMemberResponse{
			Code: data_anno_task_api.AddMemberResponse_CODE_OK,
		}, nil
	}
	//检查目标成员是否存在
	exist, err = project_dao.MemberInfoDao.Exist(ctx, req.ProjectId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.AddMemberResponse{
			Code:   data_anno_task_api.AddMemberResponse_CODE_NO_MEMBER,
			ErrMsg: "项目成员不存在",
		}, nil
	}

	userItem, err := user_dao.UserInfoDao.Get(ctx, req.MemberUserId)
	if err != nil {
		return nil, err
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = data_anno_dao.AnnoMemberDao.Insert(sessCtx, &data_anno_dao.MemberInfoDbItem{
			ProjectId:     req.ProjectId,
			AnnoProjectId: req.AnnoProjectId,
			MemberUserId:  req.MemberUserId,
			TaskCount:     0,
			DoneCount:     0,
			TimeStamp:     nowTime,
		})
		if err != nil {
			return nil, err
		}
		count, err := data_anno_dao.AnnoMemberDao.Count(sessCtx, req.AnnoProjectId)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoProjectDao.UpdateMemberCount(sessCtx, req.ProjectId, req.AnnoProjectId, count)
		if err != nil {
			return nil, err
		}
		return &data_anno_task_api.AddMemberResponse{
			Code: data_anno_task_api.AddMemberResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//记录事件
	go apiImpl.addAddAnnoMemberEvent(sessionItem, projectItem, annoProjectItem, userItem)
	return ret.(*data_anno_task_api.AddMemberResponse), nil
}

func (apiImpl *DataAnnoTaskApiImpl) ListMember(ctx context.Context, req *data_anno_task_api.ListMemberRequest) (*data_anno_task_api.ListMemberResponse, error) {
	emptyList := []*data_anno_task_api.MemberInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			InfoList: emptyList,
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			InfoList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			InfoList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	//检查信息是否存在
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.AnnoProjectId, req.ProjectId)
	if err != nil {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg:   "标注项目不存在",
			InfoList: emptyList,
		}, nil
	}
	if entryItem.EntryType != uint32(project_entry_api.ENTRY_TYPE_ENTRY_TYPE_DATA_ANNO) {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg:   "标注项目不存在",
			InfoList: emptyList,
		}, nil
	}

	hasUpdatePerm := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)

	if !hasUpdatePerm {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			InfoList: emptyList,
		}, nil
	}

	//检查标注项目是否存在
	exist, err := data_anno_dao.AnnoProjectDao.Exist(ctx, req.ProjectId, req.AnnoProjectId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.ListMemberResponse{
			Code:     data_anno_task_api.ListMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg:   "标注项目不存在",
			InfoList: emptyList,
		}, nil
	}

	memberItemList, err := data_anno_dao.AnnoMemberDao.List(ctx, req.AnnoProjectId)
	if err != nil {
		return nil, err
	}
	//补充成员信息
	userIdList := []string{}
	for _, memberItem := range memberItemList {
		userIdList = append(userIdList, memberItem.MemberUserId)
	}
	userItemList, err := user_dao.UserInfoDao.ListById(ctx, userIdList)
	if err != nil {
		return nil, err
	}
	userItemMap := map[string]*user_dao.UserInfoDbItem{}
	for _, userItem := range userItemList {
		userItemMap[userItem.UserId] = userItem
	}
	//获取项目成员列表
	memberUserIdList, err := project_dao.MemberInfoDao.ListMemberId(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	memberUserIdMap := map[string]bool{}
	for _, memberUserId := range memberUserIdList {
		memberUserIdMap[memberUserId] = true
	}

	//生成结果
	infoList := []*data_anno_task_api.MemberInfo{}
	for _, memberItem := range memberItemList {
		info := memberItem.ToMemberInfo()
		userItem, ok := userItemMap[memberItem.MemberUserId]
		if ok {
			info.DisplayName = userItem.BasicInfo.DisplayName
			info.LogoUri = userItem.BasicInfo.LogoUri
		}
		info.IsMember = memberUserIdMap[memberItem.MemberUserId]
		infoList = append(infoList, info)
	}
	return &data_anno_task_api.ListMemberResponse{
		Code:     data_anno_task_api.ListMemberResponse_CODE_OK,
		InfoList: infoList,
	}, nil
}

func (apiImpl *DataAnnoTaskApiImpl) RemoveMember(ctx context.Context, req *data_anno_task_api.RemoveMemberRequest) (*data_anno_task_api.RemoveMemberResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查信息是否存在
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.AnnoProjectId, req.ProjectId)
	if err != nil {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	if entryItem.EntryType != uint32(project_entry_api.ENTRY_TYPE_ENTRY_TYPE_DATA_ANNO) {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}

	hasUpdatePerm := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)

	if !hasUpdatePerm {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查标注项目是否存在
	annoProjectItem, err := data_anno_dao.AnnoProjectDao.Get(ctx, req.ProjectId, req.AnnoProjectId)
	if err != nil {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	//检查成员是否已经存在
	exist, err := data_anno_dao.AnnoMemberDao.Exist(ctx, req.AnnoProjectId, req.MemberUserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &data_anno_task_api.RemoveMemberResponse{
			Code:   data_anno_task_api.RemoveMemberResponse_CODE_NO_MEMBER,
			ErrMsg: "标注成员不存在",
		}, nil
	}
	userItem, err := user_dao.UserInfoDao.Get(ctx, req.MemberUserId)
	if err != nil {
		return nil, err
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = data_anno_dao.AnnoMemberDao.Remove(sessCtx, req.AnnoProjectId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		count, err := data_anno_dao.AnnoMemberDao.Count(sessCtx, req.AnnoProjectId)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoProjectDao.UpdateMemberCount(sessCtx, req.ProjectId, req.AnnoProjectId, count)
		if err != nil {
			return nil, err
		}
		//清除任务和结果
		resourceIdList, err := data_anno_dao.AnnoTaskDao.DistinctResourceByMember(sessCtx, req.AnnoProjectId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoTaskDao.RemoveByMember(sessCtx, req.AnnoProjectId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoResultDao.RemoveByMember(sessCtx, req.AnnoProjectId, req.MemberUserId)
		if err != nil {
			return nil, err
		}
		//更新资源上的计数器
		for _, resourceId := range resourceIdList {
			count, err = data_anno_dao.AnnoTaskDao.CountByResource(sessCtx, req.AnnoProjectId, resourceId)
			if err != nil {
				return nil, err
			}
			err = data_anno_dao.ResourceDao.UpdateTaskCount(sessCtx, resourceId, req.AnnoProjectId, count)
			if err != nil {
				return nil, err
			}
		}
		//更新项目任务数量
		count, err = data_anno_dao.AnnoTaskDao.CountByAnnoProject(sessCtx, req.AnnoProjectId, false, false)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoProjectDao.UpdateAllTaskCount(sessCtx, req.ProjectId, req.AnnoProjectId, count)
		if err != nil {
			return nil, err
		}
		count, err = data_anno_dao.AnnoTaskDao.CountByAnnoProject(sessCtx, req.AnnoProjectId, true, true)
		if err != nil {
			return nil, err
		}
		err = data_anno_dao.AnnoProjectDao.UpdateDoneTaskCount(sessCtx, req.ProjectId, req.AnnoProjectId, count)
		if err != nil {
			return nil, err
		}

		//去除关注
		err = watch_dao.MyWatchDao.Remove(sessCtx, req.ProjectId, req.MemberUserId, req.AnnoProjectId, uint32(project_watch_api.WATCH_TARGET_TYPE_WATCH_TARGET_ENTRY))
		if err != nil {
			return nil, err
		}
		//去除未读评论
		err = comment_dao.UnReadDao.Remove(sessCtx, req.ProjectId, req.MemberUserId, uint32(project_comment_api.COMMENT_TARGET_TYPE_COMMENT_TARGET_ENTRY), req.AnnoProjectId)
		if err != nil {
			return nil, err
		}
		return &data_anno_task_api.RemoveMemberResponse{
			Code: data_anno_task_api.RemoveMemberResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	//记录事件
	go apiImpl.addRemoveAnnoMemberEvent(sessionItem, projectItem, annoProjectItem, userItem)
	return ret.(*data_anno_task_api.RemoveMemberResponse), nil
}
